# -*- coding: utf-8 -*-
# SIS_Control.py was created by RuanYaoHuang on 2023/4/3.
import os
import queue

import sys
import ctypes
import time
from datetime import datetime

import numpy as np
import tiffile
from PIL import Image
import mysql.connector

from PyQt5.QtCore import QDateTime, Qt, QThread, pyqtSignal, pyqtSlot, QMutex
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import *

from ASI import ASI_CAMERA_INFO
from ASI import ASI_ERROR_CODE
from ASI import ASI_CONTROL_TYPE

sdk = ctypes.cdll.LoadLibrary("ASICamera2.dll")
# 获取连接的个数
sdk.ASIGetNumOfConnectedCameras.restype = ctypes.c_int
sdk.ASIGetNumOfConnectedCameras.argtypes = []
# 获取相机属性
sdk.ASIGetCameraProperty.restype = ASI_ERROR_CODE
sdk.ASIGetCameraProperty.argtypes = [ctypes.POINTER(ASI_CAMERA_INFO), ctypes.c_int]
# 打开相机
sdk.ASIOpenCamera.restype = ctypes.c_int
sdk.ASIOpenCamera.argtypes = [ctypes.c_int]
# 初始化相机
sdk.ASIInitCamera.restype = ctypes.c_int
sdk.ASIInitCamera.argtypes = [ctypes.c_int]
# 设置控制相机的参数
sdk.ASISetControlValue.restype = ASI_ERROR_CODE
sdk.ASISetControlValue.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_long, ctypes.c_int]
# 查看控制相机的参数
sdk.ASIGetControlValue.restype = ASI_ERROR_CODE
sdk.ASIGetControlValue.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_long),
								   ctypes.POINTER(ctypes.c_int)]
# 定义相机的拍照格式
sdk.ASISetROIFormat.restype = ctypes.c_int
sdk.ASISetROIFormat.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int]
# 获取相机的拍照格式
sdk.ASIGetROIFormat.restype = ASI_ERROR_CODE
sdk.ASIGetROIFormat.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_long), ctypes.POINTER(ctypes.c_long),
								ctypes.POINTER(ctypes.c_long), ctypes.POINTER(ctypes.c_long)]
# 开始录制视频
sdk.ASIStartVideoCapture.restype = ASI_ERROR_CODE
sdk.ASIStartVideoCapture.argtypes = [ctypes.c_int]
# 获取录制视频后的图像
sdk.ASIGetVideoData.restype = ASI_ERROR_CODE
sdk.ASIGetVideoData.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_ubyte), ctypes.c_long, ctypes.c_int]
# 结束录制视频
sdk.ASIStopVideoCapture.restype = ASI_ERROR_CODE
sdk.ASIStopVideoCapture.argtypes = [ctypes.c_int]
# 关闭相机
sdk.ASICloseCamera.restype = ASI_ERROR_CODE
sdk.ASICloseCamera.argtypes = [ctypes.c_int]


class View_Camera_Function(QWidget):
	def __init__(self):
		super(View_Camera_Function, self).__init__()
		self.setWindowTitle("视频采集")
		self.setStyleSheet("QWidget{background: rgb(255, 255, 255)}")
		self.setMinimumSize(1024, 960)
		self.ControlDevice = None

		self.img_type = 0

		self.height, self.view_h = 2080, 2080
		self.width, self.view_w = 3096, 3096
		self.buffer_size, self.view_size = self.width * self.height, self.width * self.height
		self.output_type, self.view_type = 'uint8', 'uint8'

		self.init_mat, self.view_mat = QImage.Format_Grayscale8, QImage.Format_Grayscale8



		self.camera_id = None
		self.get_exp_value = None
		self.get_gain_value = None

		self.liveView_thread = None
		self.save_to_local_thread = None

		self.sum_layout = QHBoxLayout()

		self.left_layout = QVBoxLayout()

		self.device_group = QGroupBox("相机")  # 相机
		self.device_combox = QComboBox()
		self.open_camera = QPushButton("开启相机")
		self.close_camera = QPushButton("关闭相机")
		self.find_camera = QPushButton("查找设备")
		self.device_layout = QHBoxLayout()

		self.image_format_group = QGroupBox("图像")  # 图像
		self.format_label = QLabel("格 式")
		self.format_combox = QComboBox()
		self.pixel_label = QLabel("分辨率")
		self.pixel_combox = QComboBox()
		self.image_format_layout = QGridLayout()

		self.param_set_group = QGroupBox("相机参数设置")  # 相机参数设置
		self.exp_label = QLabel("曝光")
		self.exp_edit = QLineEdit()
		self.exp_us = QLabel("us")
		self.exp_slider = QSlider(Qt.Horizontal)
		self.exp_check = QCheckBox("自动")

		self.gain_label = QLabel("增益")
		self.gain_edit = QLineEdit()
		self.gain_slider = QSlider(Qt.Horizontal)
		self.gain_check = QCheckBox("自动")
		self.param_set_layout = QGridLayout()

		self.image_chunck_group = QGroupBox("图像捕捉")  # 图像捕捉
		self.path_label = QLabel("路径：")
		self.path_edit = QLineEdit()
		self.path_button = QPushButton("选择")
		self.snap_button = QPushButton("捕获图像")
		self.video_button = QPushButton("录制视频")
		self.stop_button = QPushButton("停  止")
		self.image_chunck_layout = QGridLayout()

		self.ping_adjust_group = QGroupBox("屏幕显示调节")
		self.gamma_label = QLabel("伽马")
		self.gamma_view_label = QLabel("0.0")
		self.gamma_slider = QSlider(Qt.Horizontal)
		self.lightness_label = QLabel("亮度")
		self.lightness_view_label = QLabel("0.0")
		self.lightness_slider = QSlider(Qt.Horizontal)
		self.ping_adjust_layout = QGridLayout()

		self.information_group = QGroupBox("信息提取")
		self.fps_label = QLabel("帧率:")
		self.fps_view_label = QLabel()
		self.read_fps_label = QLabel("读取帧率:")
		self.read_fps_view_label = QLabel()
		self.write_fps_label = QLabel("写入帧率:")
		self.write_fps_view_label = QLabel()
		self.save_info_label = QLabel()
		self.information_layout = QGridLayout()

		self.view_label = QLabel()

		self.image_format_group.setEnabled(False)
		self.param_set_group.setEnabled(False)
		self.image_chunck_group.setEnabled(False)
		self.ping_adjust_group.setEnabled(False)
		self.information_group.setEnabled(False)

		self.setui()

	def setui(self):
		group = """QGroupBox{
										border: 2px solid white;
										border-radius:5px;
										margin-top:3ex;
										font-family:宋体;
										font: 20px; }
							QGroupBox::title{
										subcontrol-origin:margin;
										subcontrol-position:top left;
										padding:0 3px;}"""
		button = """
							QPushButton {font-size: 12pt;
											color: #404040;
											border: 2px solid rgb(241, 241, 241);
											border-radius: 15px;} 
							QPushButton:hover {	/* 鼠标悬浮在QPushButton上时的状态 */
								background-color: rgb(115, 181, 243);
								border-color:rgb(115, 181, 243);}
							QPushButton:pressed { 
								background-color: #35071f;  /* 鼠标按压在QPushButton上时的状态 */
								border-color:rgb(61, 174, 233);}"""
		combox = """
				QComboBox {
							font: 9pt "Consolas";
							border-radius: 3px;
							border:1px solid rgb(0, 0, 0);}
				QComboBox:hover {
								background-color: rgb(255, 255, 255);
								border:1px solid rgb(0, 0, 0);
								color: black;}
				QComboBox QAbstractItemView {
												border: 1px solid rgb(0, 0, 0);/*边框宽度、线形、颜色*/
												border-radius: 1px;/*圆角*/
												min-width: 2em;   /*# 组合框的最小宽度*/
												padding: 1px 2px 1px 2px;  /*针对于组合框中的文本内容*/
												selection-color: rgb(255, 255, 255);
												selection-background-color: rgb(72, 156, 236);
												background-color: rgb(255, 255, 255);/*背景颜色*/}"""
		slid = """QSlider::groove:horizontal {border: 0px solid #bbb;}

						/*1.滑动过的槽设计参数*/
						QSlider::sub-page:horizontal{
									background: rgb(90,49,255); /*槽颜色*/
									border-radius: 2px; /*外环区域倒圆角度*/
									margin-top:8px; /*上遮住区域高度*/  
									margin-bottom:8px;  /*下遮住区域高度*/ }

						/*2.未滑动过的槽设计参数*/
						QSlider::add-page:horizontal {
									background: rgb(255,255, 255);  /*槽颜色*/
									border: 0px solid #777; /*外环大小0px就是不显示，默认也是0*/
									border-radius: 2px; /*外环区域倒圆角度*/
									margin-top:9px; /*上遮住区域高度*/
									margin-bottom:9px;  /*下遮住区域高度*/}

						/*3.平时滑动的滑块设计参数*/
						QSlider::handle:horizontal {
									background: rgb(193,204,208);   /*滑块颜色*/
									width: 5px; /*滑块的宽度*/
									border: 1px solid rgb(193,204,208); /*滑块外环为1px，再加颜色*/
									border-radius: 2px; /*滑块外环倒圆角度*/
									margin-top:6px; /*上遮住区域高度*/
									margin-bottom:6px;  /*下遮住区域高度*/}

						/*4.手动拉动时显示的滑块设计参数*/
						QSlider::handle:horizontal:hover {
							background: rgb(193,204,208);   /*滑块颜色*/
							width: 10px;    /*滑块的宽度*/
							border: 1px solid rgb(193,204,208); /*滑块外环为1px，再加颜色*/
							border-radius: 5px; /*滑块外环倒圆角度*/ 
							margin-top:4px; /*上遮住区域高度*/
							margin-bottom:4px;  /*下遮住区域高度*/}
					"""
		label = """QLabel{font: 11pt "华文宋体";background:rgb(255, 255, 255)}"""

		self.left_layout.addWidget(self.device_group)
		self.device_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.device_group.setStyleSheet(group)
		self.device_group.setLayout(self.device_layout)
		self.device_layout.addWidget(self.device_combox)
		self.device_layout.addWidget(self.open_camera)
		self.device_layout.addWidget(self.close_camera)
		self.device_layout.addWidget(self.find_camera)
		# -----------------------------------------------------
		spacer1 = QSpacerItem(50, 10, QSizePolicy.Expanding, QSizePolicy.Fixed)  # 弹簧
		spacer2 = QSpacerItem(50, 10, QSizePolicy.Expanding, QSizePolicy.Fixed)  # 弹簧
		self.left_layout.addWidget(self.image_format_group)
		self.image_format_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.image_format_group.setStyleSheet(group)
		self.image_format_group.setLayout(self.image_format_layout)
		self.image_format_layout.addWidget(self.format_label, 0, 0, 1, 1)
		self.image_format_layout.addWidget(self.format_combox, 0, 1, 1, 1)
		self.image_format_layout.addItem(spacer1, 0, 2, 1, 1)
		self.image_format_layout.addWidget(self.pixel_label, 1, 0, 1, 1)
		self.image_format_layout.addWidget(self.pixel_combox, 1, 1, 1, 1)
		self.image_format_layout.addItem(spacer2, 1, 2, 1, 1)
		# -----------------------------------------------------
		self.left_layout.addWidget(self.param_set_group)
		self.param_set_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.param_set_group.setStyleSheet(group)
		self.param_set_group.setLayout(self.param_set_layout)
		self.param_set_layout.addWidget(self.exp_label, 0, 0, 1, 1)
		self.param_set_layout.addWidget(self.exp_edit, 0, 1, 1, 1)
		self.param_set_layout.addWidget(self.exp_us, 0, 2, 1, 1)
		self.param_set_layout.addWidget(self.exp_slider, 1, 0, 1, 3)
		self.param_set_layout.addWidget(self.exp_check, 1, 3, 1, 1)
		self.param_set_layout.addWidget(self.gain_label, 2, 0, 1, 1)
		self.param_set_layout.addWidget(self.gain_edit, 2, 1, 1, 1)
		self.param_set_layout.addWidget(self.gain_slider, 3, 0, 1, 3)
		self.param_set_layout.addWidget(self.gain_check, 3, 3, 1, 1)
		# -----------------------------------------------------
		self.left_layout.addWidget(self.image_chunck_group)
		self.image_chunck_group.setStyleSheet(group)
		self.image_chunck_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.image_chunck_group.setLayout(self.image_chunck_layout)
		self.image_chunck_layout.addWidget(self.path_label, 0, 0, 1, 1)
		self.image_chunck_layout.addWidget(self.path_edit, 0, 1, 1, 2)
		self.image_chunck_layout.addWidget(self.path_button, 0, 3, 1, 1)
		self.image_chunck_layout.addWidget(self.snap_button, 1, 0, 1, 2)
		self.image_chunck_layout.addWidget(self.video_button, 1, 2, 1, 2)
		self.image_chunck_layout.addWidget(self.stop_button, 2, 0, 1, 4)
		# -----------------------------------------------------
		self.left_layout.addWidget(self.ping_adjust_group)
		self.ping_adjust_group.setStyleSheet(group)
		self.ping_adjust_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.ping_adjust_group.setLayout(self.ping_adjust_layout)
		self.ping_adjust_layout.addWidget(self.gamma_label, 0, 0, 1, 1)
		self.ping_adjust_layout.addWidget(self.gamma_view_label, 0, 1, 1, 1)
		self.ping_adjust_layout.addWidget(self.gamma_slider, 1, 0, 1, 4)

		self.ping_adjust_layout.addWidget(self.lightness_label, 2, 0, 1, 1)
		self.ping_adjust_layout.addWidget(self.lightness_view_label, 2, 1, 1, 1)
		self.ping_adjust_layout.addWidget(self.lightness_slider, 3, 0, 1, 4)

		self.left_layout.addWidget(self.information_group)
		self.information_group.setStyleSheet(group)
		self.information_group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
		self.information_group.setLayout(self.information_layout)

		self.information_layout.addWidget(self.fps_label, 0, 0, 1, 1)
		self.information_layout.addWidget(self.fps_view_label, 0, 1, 1, 2)
		self.information_layout.addWidget(self.read_fps_label, 1, 0, 1, 1)
		self.information_layout.addWidget(self.read_fps_view_label, 1, 1, 1, 2)
		self.information_layout.addWidget(self.write_fps_label, 2, 0, 1, 1)
		self.information_layout.addWidget(self.write_fps_view_label, 2, 1, 1, 2)
		self.information_layout.addWidget(self.save_info_label, 3, 0, 1, 3)

		# --------------------------------------------
		self.device_combox.setFixedWidth(120)
		self.device_combox.setFixedHeight(32)
		self.device_combox.setStyleSheet(combox)
		self.open_camera.setFixedWidth(65)
		self.open_camera.setFixedHeight(30)
		self.open_camera.setStyleSheet(button)
		self.close_camera.setFixedWidth(65)
		self.close_camera.setFixedHeight(30)
		self.close_camera.setStyleSheet(button)
		self.find_camera.setFixedWidth(65)
		self.find_camera.setFixedHeight(30)
		self.find_camera.setStyleSheet(button)
		# =================================================
		self.format_label.setFixedWidth(51)
		self.format_label.setFixedHeight(40)
		self.format_label.setStyleSheet(label)
		self.format_combox.setFixedWidth(238)
		self.format_combox.setFixedHeight(32)
		self.format_combox.setStyleSheet(combox)
		format_item = ['RAW8', 'RAW16']
		self.format_combox.addItems(format_item)
		self.pixel_label.setFixedWidth(51)
		self.pixel_label.setFixedHeight(40)
		self.pixel_label.setStyleSheet(label)
		self.pixel_combox.setFixedWidth(238)
		self.pixel_combox.setFixedHeight(32)
		self.pixel_combox.setStyleSheet(combox)
		pixel_item = ['3096*2080', '2560*1440', '1920*1080', '1600*900', '1360*768', '1280*720', '1024*768', '640*480',
					  '320*240']
		self.pixel_combox.addItems(pixel_item)
		# =================================================
		self.exp_label.setFixedWidth(64)
		self.exp_label.setFixedHeight(32)
		self.exp_label.setStyleSheet(label)
		self.exp_edit.setFixedWidth(101)
		self.exp_edit.setFixedHeight(32)
		self.exp_us.setFixedWidth(64)
		self.exp_us.setFixedHeight(32)
		self.exp_us.setStyleSheet(label)
		self.exp_slider.setFixedWidth(266)
		self.exp_slider.setFixedHeight(30)
		self.exp_slider.setStyleSheet(slid)
		self.exp_slider.setMinimum(32)
		self.exp_slider.setMaximum(2000000000)
		self.exp_slider.setSingleStep(8)
		self.gain_label.setFixedWidth(64)
		self.gain_label.setFixedHeight(32)
		self.gain_label.setStyleSheet(label)
		self.gain_edit.setFixedWidth(101)
		self.gain_edit.setFixedHeight(32)
		self.gain_slider.setFixedWidth(266)
		self.gain_slider.setFixedHeight(30)
		self.gain_slider.setStyleSheet(slid)
		self.gain_slider.setMinimum(0)
		self.gain_slider.setMaximum(510)
		self.gain_slider.setSingleStep(10)
		# =================================================
		self.path_label.setFixedWidth(28)
		self.path_label.setFixedHeight(32)
		self.path_label.setStyleSheet(label)
		self.path_edit.setFixedWidth(260)
		self.path_edit.setFixedHeight(32)
		self.path_button.setFixedWidth(35)
		self.path_button.setFixedHeight(30)
		self.path_button.setStyleSheet(button)
		self.snap_button.setFixedWidth(150)
		self.snap_button.setFixedHeight(35)
		self.snap_button.setStyleSheet(button)
		self.video_button.setFixedWidth(150)
		self.video_button.setFixedHeight(35)
		self.video_button.setStyleSheet(button)
		self.stop_button.setFixedWidth(320)
		self.stop_button.setFixedHeight(40)
		self.stop_button.setStyleSheet(button)
		# =================================================
		self.gamma_label.setFixedWidth(121)
		self.gamma_label.setFixedHeight(25)
		self.gamma_label.setStyleSheet(label)
		self.gamma_view_label.setFixedWidth(70)
		self.gamma_view_label.setFixedHeight(32)
		self.gamma_view_label.setStyleSheet(label)
		self.gamma_slider.setFixedWidth(321)
		self.gamma_slider.setFixedHeight(30)
		self.gamma_slider.setStyleSheet(slid)
		self.gamma_slider.setMaximum(200)
		self.gamma_slider.setSingleStep(1)
		self.lightness_label.setFixedWidth(121)
		self.lightness_label.setFixedHeight(25)
		self.lightness_label.setStyleSheet(label)
		self.lightness_view_label.setFixedWidth(70)
		self.lightness_view_label.setFixedHeight(32)
		self.lightness_view_label.setStyleSheet(label)
		self.lightness_slider.setFixedWidth(321)
		self.lightness_slider.setFixedHeight(30)
		self.lightness_slider.setStyleSheet(slid)
		self.lightness_slider.setMaximum(200)
		self.lightness_slider.setSingleStep(1)
		# =================================================
		self.fps_label.setFixedWidth(65)
		self.fps_label.setFixedHeight(25)
		self.fps_label.setStyleSheet(label)
		self.fps_view_label.setFixedWidth(60)
		self.fps_view_label.setFixedHeight(25)
		self.fps_view_label.setStyleSheet(label)
		self.read_fps_label.setFixedWidth(65)
		self.read_fps_label.setFixedHeight(25)
		self.read_fps_label.setStyleSheet(label)
		self.read_fps_view_label.setFixedWidth(60)
		self.read_fps_view_label.setFixedHeight(25)
		self.read_fps_view_label.setStyleSheet(label)
		self.write_fps_label.setFixedWidth(65)
		self.write_fps_label.setFixedHeight(25)
		self.write_fps_label.setStyleSheet(label)
		self.write_fps_view_label.setFixedWidth(60)
		self.write_fps_view_label.setFixedHeight(25)
		self.write_fps_view_label.setStyleSheet(label)
		self.save_info_label.setFixedWidth(280)
		self.save_info_label.setFixedHeight(25)
		self.save_info_label.setStyleSheet(label)

		# =================================================

		self.view_label.setMinimumSize(800, 800)
		self.view_label.setStyleSheet("""QLabel{background:rgb(255, 255, 255)}""")
		self.sum_layout.addLayout(self.left_layout)
		self.sum_layout.addWidget(self.view_label)
		self.setLayout(self.sum_layout)

		self.exp_check.stateChanged.connect(self.on_exp_checked_state_changed)
		self.exp_slider.sliderMoved.connect(self.exp_slider_changed)
		self.exp_edit.returnPressed.connect(self.exp_edit_changed)

		self.gain_check.stateChanged.connect(self.on_gain_checked_state_changed)
		self.gain_slider.sliderMoved.connect(self.gain_slider_changed)
		self.gain_edit.returnPressed.connect(self.gain_edit_changed)

		self.lightness_slider.sliderMoved.connect(self.on_lightness_slider_value_changed)
		self.gamma_slider.sliderMoved.connect(self.on_gamma_slider_value_changed)

		self.path_button.clicked.connect(self.on_choose_path_button_clicked)

		self.format_combox.currentIndexChanged.connect(self.format_combox_control)
		self.pixel_combox.currentIndexChanged.connect(self.pixel_combox_control)
		#
		self.find_camera.clicked.connect(self.on_find_camera_button_clicked)
		self.open_camera.clicked.connect(self.on_open_camera_button_clicked)
		self.close_camera.clicked.connect(self.on_close_camera_button_clicked)

		self.video_button.clicked.connect(self.on_save_video_button_clicked)
		self.stop_button.clicked.connect(self.on_stop_save_video_button_clicked)


# 查找设备
	def on_find_camera_button_clicked(self):
		num_cameras = sdk.ASIGetNumOfConnectedCameras()
		print(f"Step1: Number of connected cameras: {num_cameras}")
		cam_info = ASI_CAMERA_INFO()
		ret_property = sdk.ASIGetCameraProperty(ctypes.byref(cam_info), ctypes.c_int(0))
		if ret_property == ASI_ERROR_CODE.ASI_SUCCESS:
			print("Failed to get camera properties")
		else:
			print(f"Step2: Camera properties:{cam_info}, Camera name: {cam_info.Name}")

		device_name = cam_info.Name
		if device_name != b'':
			self.device_combox.addItem(str(device_name)[2:-1])
# 选择分辨率尺寸
	def pixel_combox_control(self, index):
		area = self.pixel_combox.currentText()
		if 0 <= index < 7:
			self.width = int(area[0:4])
			self.height = int(area[5:])
		else:
			self.width = int(area[0:3])
			self.height = int(area[4:])

		print(f'width: {self.width}')
		print(f'height: {self.height}')
# 选择位深
	def format_combox_control(self, index):
		if index == 0:
			self.img_type = 0
			self.buffer_size = self.width * self.height
			self.output_type = 'uint8'
			self.init_mat = QImage.Format_Grayscale8
		else:
			self.img_type = 2
			self.buffer_size = self.width * self.height * 2
			self.output_type = 'uint16'
			self.init_mat = QImage.Format_Grayscale16
# 选择保存地址
	def on_choose_path_button_clicked(self):
		try:
			dir_path = QFileDialog.getExistingDirectory(self, "本地文件", "./")
			self.path_edit.setText(str(dir_path))
		except Exception as e:
			print(f'clicked to open the local dir drug Error!{e}')
# 调节亮度
	def on_lightness_slider_value_changed(self, index):
		self.lightness_view_label.setText(str(index))
		# 设置相机的亮度
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_AUTO_TARGET_BRIGHTNESS,
							   ctypes.c_long(index), ctypes.c_int(0))
# 调节伽马
	def on_gamma_slider_value_changed(self, index):
		self.gamma_view_label.setText(str(index))
		# 设置相机的亮度
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_GAMMA,
							   ctypes.c_long(index), ctypes.c_int(0))
# 自动调节增益
	def on_gain_checked_state_changed(self, status):
		if status == Qt.Checked:
			self.gain_edit.setDisabled(True)
			self.gain_slider.setDisabled(True)
			# 设置相机的曝光
			sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_GAIN,
								   ctypes.c_long(self.gain_slider.value()), ctypes.c_int(1))
			self.get_gain_value = get_gain_value_thread(self.camera_id)
			self.get_gain_value.gain_value.connect(self.set_gain_slider)
			self.get_gain_value.start()
		else:
			sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_GAIN,
			                       ctypes.c_long(self.gain_slider.value()), ctypes.c_int(0))
			self.gain_edit.setDisabled(False)
			self.gain_slider.setDisabled(False)
			self.get_gain_value.stop()
# 调节增益线程回传的数值
	def set_gain_slider(self, value):
		self.gain_slider.setValue(value)
		self.gain_edit.setText(str(value))
# slider调节增益
	def gain_slider_changed(self, index):
		self.gain_edit.setText(str(index))
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_GAIN,
			                       ctypes.c_long(index), ctypes.c_int(0))
# linedit调节增益
	def gain_edit_changed(self):
		value = int(self.gain_edit.text())
		self.gain_slider.setValue(value)
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_GAIN,
			                       ctypes.c_long(value), ctypes.c_int(0))
# 自动调节曝光
	def on_exp_checked_state_changed(self, status):
		if status == Qt.Checked:
			self.exp_edit.setDisabled(True)
			self.exp_slider.setDisabled(True)
			self.exp_us.setDisabled(True)
			# 设置相机的曝光
			sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_EXPOSURE,
								   ctypes.c_long(self.exp_slider.value()), ctypes.c_int(1))
			self.get_exp_value = get_exposure_value_thread(self.camera_id)
			self.get_exp_value.exp_value.connect(self.set_exp_slider)
			self.get_exp_value.start()

		else:
			sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_EXPOSURE,
			                       ctypes.c_long(self.exp_slider.value()), ctypes.c_int(0))
			self.exp_edit.setDisabled(False)
			self.exp_slider.setDisabled(False)
			self.exp_us.setDisabled(False)
			self.get_exp_value.stop()
# 曝光线程回传的数值
	def set_exp_slider(self, value):
		self.exp_slider.setValue(value)
		self.exp_edit.setText(str(value))
# slider调节曝光
	def exp_slider_changed(self, index):
		self.exp_edit.setText(str(index))
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_EXPOSURE,
			                       ctypes.c_long(index), ctypes.c_int(0))
# linedit调节曝光
	def exp_edit_changed(self):
		value = int(self.exp_edit.text())
		self.exp_slider.setValue(value)
		sdk.ASISetControlValue(self.camera_id.value, ASI_CONTROL_TYPE.ASI_EXPOSURE,
			                       ctypes.c_long(value), ctypes.c_int(0))
# 关闭设备
	def on_close_camera_button_clicked(self):
		self.liveView_thread.stop()
		sdk.ASIStopVideoCapture(self.camera_id.value)
		sdk.ASICloseCamera(self.camera_id.value)
		self.image_format_group.setEnabled(False)
		self.param_set_group.setEnabled(False)
		self.image_chunck_group.setEnabled(False)
		self.ping_adjust_group.setEnabled(False)
		self.information_group.setEnabled(False)
# 开机前的准备
	def get_param_value(self, parament):
		_param = ctypes.c_long()
		_status = ctypes.c_int()
		sdk.ASIGetControlValue(self.camera_id.value, parament,
		                       ctypes.byref(_param),
		                       ctypes.byref(_status))
		return _param.value, _status.value
	def initial_device(self):
		print(f"Step3: Open the Camera, Camera ID is: {self.camera_id.value}")
		initial_camera = sdk.ASIInitCamera(self.camera_id.value)
		if initial_camera == 0:
			self.image_format_group.setEnabled(True)
			self.param_set_group.setEnabled(True)
			self.image_chunck_group.setEnabled(True)
			self.ping_adjust_group.setEnabled(True)
			self.information_group.setEnabled(True)
			print("Step4: Camera has to initialize")
			print("Step5: View Camera param")
			exp_param, exp_status = self.get_param_value(ASI_CONTROL_TYPE.ASI_EXPOSURE)
			print(f'    expourse param value is {exp_param}, status is {exp_status}')
			gain_param, gain_status = self.get_param_value(ASI_CONTROL_TYPE.ASI_GAIN)
			print(f'    gain param value is {gain_param}, status is {gain_status}')
			gamma_param, gamma_status = self.get_param_value(ASI_CONTROL_TYPE.ASI_GAMMA)
			print(f'    gamma param value is {gamma_param}, status is {gamma_status}')
			light_param, light_status = self.get_param_value(ASI_CONTROL_TYPE.ASI_AUTO_TARGET_BRIGHTNESS)
			print(f'    lightness param value is {light_param}, status is {light_status}')

			self.exp_edit.setText(str(exp_param))
			self.exp_slider.setValue(exp_param)
			if exp_status == 1:
				self.exp_check.setChecked(True)
			else:
				self.exp_check.setChecked(False)

			self.gain_edit.setText(str(gain_param))
			self.gain_slider.setValue(gain_param)
			if gain_status == 1:
				self.gain_check.setChecked(True)
			else:
				self.gain_check.setChecked(False)

			self.gamma_slider.setValue(gamma_param)
			self.lightness_slider.setValue(light_param)

			print(f'buffer size is {self.buffer_size}, output format is {self.output_type}\n\t'
				f'height is {self.height}, width is {self.width}, img_type is {self.img_type}')
			cam_info = ASI_CAMERA_INFO()
			sdk.ASIGetCameraProperty(ctypes.byref(cam_info), self.camera_id.value)

			self.view_h = self.height
			self.view_w = self.width
			self.view_size = self.buffer_size
			self.view_type = self.output_type
			self.view_mat = self.init_mat

			sdk.ASISetROIFormat(self.camera_id.value, ctypes.c_int(self.width), ctypes.c_int(self.height), 1,
								ctypes.c_int(self.img_type))

			# 查看相机的拍照格式
			cur_w = ctypes.c_long()
			cur_h = ctypes.c_long()
			cur_bin = ctypes.c_long()
			cur_img_type = ctypes.c_long()
			ret = sdk.ASIGetROIFormat(self.camera_id.value, ctypes.byref(cur_w), ctypes.byref(cur_h),
									  ctypes.byref(cur_bin),
									  ctypes.byref(cur_img_type))

			if ret.value == ASI_ERROR_CODE.ASI_SUCCESS:
				if cur_w.value == self.width and cur_h.value == self.height and cur_img_type.value == self.img_type:
					print("Camera RIOFormat set Succeed!")
				else:
					print("Camera RIOFormat set Failed")
			else:
				print("Can't access camera RIOFormat")
		else:
			print("Failed to initialize the SDK")
# 显示照片到label
	def show_img(self, image):
		re_img = image.reshape((self.view_h, self.view_w))
		q_image = QImage(re_img, re_img.shape[1], re_img.shape[0], self.view_mat)
		q_pixmap = QPixmap.fromImage(q_image)
		self.view_label.setPixmap(q_pixmap)
		self.view_label.setScaledContents(True)
# 显示fps到label
	def show_fps(self, value):
		self.fps_view_label.setText(str(value))
# 打开设备并开启视频流传输
	def on_open_camera_button_clicked(self):
		self.camera_id = ctypes.c_int()
		open_camera = sdk.ASIOpenCamera(self.camera_id)
		if open_camera == 0:
			self.initial_device()
		else:
			print("Failed to get camera ID")
		try:
			self.liveView_thread = Open_deviceThread(self.camera_id, self.view_size, self.view_type)
			self.liveView_thread.one_dim_matrix.connect(self.show_img)
			self.liveView_thread.fps.connect(self.show_fps)
			self.liveView_thread.start()
		except Exception as e:
			print(f'live thread has drug error:{e}')
# 停止保存线程
	def on_stop_save_video_button_clicked(self):
		try:
			self.liveView_thread.one_dim_matrix.disconnect(self.save_to_local_thread.receive_image_data)
			self.save_to_local_thread.stop()
		except Exception as e:
			print(e)

# 开启保存线程
	def on_save_video_button_clicked(self):
		path = self.path_edit.text()
		fps = float(self.fps_view_label.text())
		self.save_to_local_thread = save_to_video_thread(path, fps)
		self.liveView_thread.one_dim_matrix.connect(self.save_to_local_thread.receive_image_data)
		self.save_to_local_thread.receive_img.connect(self.receive_img_nums)
		self.save_to_local_thread.save_img.connect(self.save_img_nums)
		self.save_to_local_thread.start()
# 保存时的读取个数
	def receive_img_nums(self, num):
		self.read_fps_view_label.setText(str(num))
# 保存个数
	def save_img_nums(self, num):
		self.write_fps_view_label.setText(str(num))

# 保存视频线程
class save_to_video_thread(QThread):
	receive_img = pyqtSignal(int)
	save_img = pyqtSignal(int)
	def __init__(self, path: str, fps: float, parent=None):
		super(save_to_video_thread, self).__init__(parent)
		self.is_running = True
		self.fps = fps
		self.receive_count = 1
		self.save_count = 1
		self.timeout = 5.0
		self.current_time = QDateTime.currentDateTime().toString("yyyy-MM-dd HH-mm-ss")  # 时间
		self.Folder = f'{path}/{self.current_time}'
		if not os.path.exists(self.Folder):
			os.makedirs(self.Folder)
		self.image_queue = queue.Queue()
		self.lock = QMutex()

	@pyqtSlot(np.ndarray)
	def receive_image_data(self, image_data):
		image = image_data.reshape((2080, 3096))
		self.image_queue.put(image)
		self.receive_img.emit(self.receive_count)
		self.receive_count += 1

	def run(self):
		print(f'save_to_video_thread is action, and is_running value is : {self.is_running}')
		while self.is_running:
			try:
				self.lock.lock()
				all_name = f'{self.Folder}/{str(self.current_time)}.tiff'
				with tiffile.TiffWriter(all_name, bigtiff=True) as tif:
					while True:
						try:
							frame_data = self.image_queue.get(timeout=1)
							tif.write(frame_data, metadata={'fps': self.fps})
						except queue.Empty:
								break
				with open(all_name, 'wb') as f:
					f.write(self.image_queue.get(timeout=self.timeout).tobytes())
				self.save_img.emit(self.save_count)
				self.save_count += 1
				time.sleep(0.1)
				self.lock.unlock()

			except queue.Empty:
				self.is_running = False
			except Exception as e:
				print(f'抛出异常{e}')
		print('jump out thread while')
		self.wait()

		print(f'save_to_video_thread is stop, and is_running value is : {self.is_running}')

	def stop(self):
		self.is_running = False
		self.lock.unlock()
		print(f'save_to_video_thread is Stop, and is_running value is : {self.is_running}')
		self.wait()

# 开启设备线程
class Open_deviceThread(QThread):
	one_dim_matrix = pyqtSignal(np.ndarray)
	fps = pyqtSignal(float)
	def __init__(self, camera_id, buf_size, img_type, parent=None):
		'''
		:param camera_id: 相机
		:param buf_size: 缓存空间大小
		:param img_type: 图像类型
		:param parent: None
		'''
		super(Open_deviceThread, self).__init__(parent)
		self.camera_id = camera_id
		self._buf_size = buf_size
		self._img_type = img_type
		self.is_running = True
		self._lock = QMutex()
	def run(self):
		try:
			sdk.ASIStartVideoCapture(self.camera_id.value)
			_buf = (ctypes.c_ubyte * self._buf_size)()
			_count = 1
			start_time = time.time()
			while self.is_running:
				# self._lock.lock()
				try:
					ret_get_data = sdk.ASIGetVideoData(self.camera_id.value, _buf, self._buf_size, ctypes.c_int(100000))
					if ret_get_data.value == ASI_ERROR_CODE.ASI_ERROR_CAMERA_CLOSED:
						print("Step9: camera didn't open")
						break
					elif ret_get_data.value == ASI_ERROR_CODE.ASI_ERROR_INVALID_ID:
						print("Step9: no camera of this ID is connected or ID value is out of boundary")
						break
					elif ret_get_data.value == ASI_ERROR_CODE.ASI_ERROR_TIMEOUT:
						print("Step9: no image get and timeout")
						break
					else:
						image = np.frombuffer(_buf, dtype=self._img_type)
					self.one_dim_matrix.emit(image)
					elapsed_time = time.time() - start_time
					self.fps.emit(round(_count / elapsed_time, 2))
					_count += 1
				except UnboundLocalError as u:
					print(u)
			# self._lock.unlock()

		except Exception as e:
			print(f'开启相机线程: {e}')

	def stop(self):
		self.is_running = False
		print(f'Open_deviceThread is Stop, and is_running value is : {self.is_running}')
		self.wait()

# 自动调节线程
class auto_get_value_thread(QThread):
	param_value = pyqtSignal(int)

	def __init__(self, camera, parament, parent=None):
		'''

		:param camera: 相机
		:param parament: 相机参数
		:param parent: None
		'''
		super(auto_get_value_thread, self).__init__(parent)
		self.camera = camera
		self.param = parament
		self.is_running = True
		self._lock = QMutex()

	def run(self):
		if self.camera is not None:
			while self.is_running:
				_param = ctypes.c_long()
				_status = ctypes.c_int()
				sdk.ASIGetControlValue(self.camera.value, self.param,
									   ctypes.byref(_param),
									   ctypes.byref(_status))
				self.param_value.emit(_param.value)
	def stop(self):
		self.is_running = False
		print(f'auto_get_value_thread is Stop, and is_running value is : {self.is_running}')
		self.wait()
# 自动调节增益线程
class get_gain_value_thread(QThread):
	gain_value = pyqtSignal(int)
	def __init__(self, camera, parent=None):
		'''

		:param camera: 相机
		:param parent: None
		'''
		super(get_gain_value_thread, self).__init__(parent)
		self.camera = camera
		self.is_running = True

	def run(self):
		if self.camera is not None:
			while self.is_running:
				gain_param = ctypes.c_long()
				gain_status = ctypes.c_int()
				sdk.ASIGetControlValue(self.camera.value, ASI_CONTROL_TYPE.ASI_GAIN,
									   ctypes.byref(gain_param),
									   ctypes.byref(gain_status))
				self.gain_value.emit(gain_param.value)
	def stop(self):
		self.is_running = False
		print(f'get_gain_value_thread is Stop, and is_running value is : {self.is_running}')
		self.wait()
# 自动调节曝光线程
class get_exposure_value_thread(QThread):
	exp_value = pyqtSignal(int)
	def __init__(self, camera, parent=None):
		'''

		:param camera: 相机
		:param parent: None
		'''
		super(get_exposure_value_thread, self).__init__(parent)
		self.camera = camera
		self.is_running = True

	def run(self):
		if self.camera is not None:
			while self.is_running:
				try:
					exp_param = ctypes.c_long()
					exp_status = ctypes.c_int()
					sdk.ASIGetControlValue(self.camera.value, ASI_CONTROL_TYPE.ASI_EXPOSURE,
										   ctypes.byref(exp_param),
										   ctypes.byref(exp_status))
					self.exp_value.emit(exp_param.value)
				except Exception as e:
					print(e)
	def stop(self):
		self.is_running = False
		print(f'get_exposure_value_thread is Stop, and is_running value is : {self.is_running}')
		self.wait()



if __name__ == '__main__':
	app = QApplication(sys.argv)
	OpenDeviceORTransImage = View_Camera_Function()
	OpenDeviceORTransImage.show()
	exit(app.exec_())